package com.icesoft.core.common.helper;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import com.icesoft.core.common.helper.tree.TreeUtils;

public abstract class TypeUtil {
	private static final int TOP_ID = 1;
	public static TypeTreeDTO getSuperArgumentTypes(Class<?> clz) {
		return getArgumentTypes(getSuperGenricTypes(clz));
	}

	public static TypeTreeDTO getArgumentTypes(Type... types) {
		Queue<Type> queue = new LinkedList<>();
		queue.addAll(Arrays.asList(types));
		return getArgumentTypes(queue);
	}

	private static TypeTreeDTO getArgumentTypes(Queue<Type> queue) {
		if (queue.isEmpty()) {
			throw new IllegalArgumentException("类型为空");
		}
		List<TypeTreeDTO> list = new ArrayList<>();
		TypeTreeDTO top = null;
		int id = 0;
		TypeTreeDTO lastParentType = null;
		TypeTreeDTO lastType = null;
		while (!queue.isEmpty()) {
			Type type = queue.poll();
			if (type == null) {
				if (lastType != null) {
					if (lastParentType != null) {
						lastType.setPid(lastParentType.getId());
						list.add(lastType);
					} else {
						top = newNode(lastType.getType(), TOP_ID, 0);
					}
				}
				continue;
			}
			if (type instanceof ParameterizedType) {
				ParameterizedType pt = (ParameterizedType) type;
				Class<?> rowType = (Class<?>) pt.getRawType();
				lastParentType = lastType;
				lastType = newNode(rowType, ++id, lastType != null ? lastType.getId() : 0);
				queue.add(null);
				queue.addAll(Arrays.asList(pt.getActualTypeArguments()));
				continue;
			}
			if (lastType == null) {
				top = newNode(type, TOP_ID, 0);
			} else {
				list.add(newNode(type, ++id, lastType.getId()));
			}
		}
		top = TreeUtils.hierarchy(top, list);
		return top;
	}

	public static Class<?> getSuperGenricType(final Class<?> clz) {
		return getSuperGenricType(clz, 0);
	}

	public static Class<?> getSuperGenricType(final Class<?> clz, final int index) {
		return (Class<?>) getSuperGenricTypes(clz)[index];
	}

	public static Type[] getSuperGenricTypes(final Class<?> clz) {
		Class<?> superClass = clz;
		Type type = superClass.getGenericSuperclass();
		while (superClass != Object.class && !(type instanceof ParameterizedType)) {
			superClass = superClass.getSuperclass();
			type = superClass.getGenericSuperclass();
		}
		if (superClass == Object.class) {
			throw new IllegalArgumentException("父类不含泛型类型：" + clz);
		}
		ParameterizedType genericSuperclass = (ParameterizedType) type;
		return genericSuperclass.getActualTypeArguments();
	}

	private static TypeTreeDTO newNode(Type type, int id, int pid) {
		if (type instanceof TypeVariable) {

		}
		TypeTreeDTO argumentType = new TypeTreeDTO();
		argumentType.setType((Class<?>) type);
		argumentType.setId(id);
		argumentType.setPid(pid);
		argumentType.setChildren(new ArrayList<>());
		return argumentType;
	}
}
